1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30 import java.util.*;
31 import java.util.zip.*;
32 import java.util.jar.*;
33 import java.io.*;
34
35 public class Assortment {
36 static int passed = 0, failed = 0;
37
38 static void fail(String msg) {
39 failed++;
40 new Exception(msg).printStackTrace();
41 }
42
43 static void unexpected(Throwable t) {
44 failed++;
45 t.printStackTrace();
46 }
47
48 static void check(boolean condition, String msg) {
49 if (! condition)
50 fail(msg);
51 }
52
53 static void check(boolean condition) {
54 check(condition, "Something's wrong");
55 }
56
57 private static class Entry {
58 private String name;
59 private int method;
60 private byte[] data;
61 private byte[] extra;
62 private String comment;
63
64 Entry(String name,
65 int method,
66 byte[] data,
67 byte[] extra,
68 String comment) {
69 this.name = name;
70 this.method = method;
71 this.data = data;
72 this.extra = extra;
73 this.comment = comment;
74 }
75
76 void write(ZipOutputStream s) throws Exception {
77 ZipEntry e = new ZipEntry(name);
78 CRC32 crc32 = new CRC32();
79 e.setMethod(method);
80 if (method == ZipEntry.STORED) {
81 e.setSize(data == null ? 0 : data.length);
82 crc32.reset();
83 if (data != null) crc32.update(data);
84 e.setCrc(crc32.getValue());
85 } else {
86 e.setSize(0);
87 e.setCrc(0);
88 }
89 if (comment != null) e.setComment(comment);
90 if (extra != null) e.setExtra(extra);
91 s.putNextEntry(e);
92 if (data != null) s.write(data);
93 }
94
95 byte[] getData(ZipFile f, ZipEntry e) throws Exception {
96 byte[] fdata = new byte[(int)e.getSize()];
97 InputStream is = f.getInputStream(e);
98 is.read(fdata);
99 return fdata;
100 }
101
102 void verify(ZipFile f) throws Exception {
103 ZipEntry e = f.getEntry(name);
104 byte[] data = (this.data == null) ? new byte[]{} : this.data;
105 byte[] extra = (this.extra != null && this.extra.length == 0) ?
106 null : this.extra;
107 check(name.equals(e.getName()));
108 check(method == e.getMethod());
109 check((((comment == null) || comment.equals(""))
110 && (e.getComment() == null))
111 || comment.equals(e.getComment()));
112 check(Arrays.equals(extra, e.getExtra()));
113 check(Arrays.equals(data, getData(f, e)));
114 check(e.getSize() == data.length);
115 check((method == ZipEntry.DEFLATED) ||
116 (e.getCompressedSize() == data.length));
117 }
118
119 void verify(JarInputStream jis) throws Exception {
120
121 if (name.equals("meta-iNf/ManIfEst.Mf"))
122 return;
123 ZipEntry e = jis.getNextEntry();
124
125 byte[] data = (this.data == null) ? new byte[]{} : this.data;
126 byte[] otherData = new byte[data.length];
127 jis.read(otherData);
128 check(Arrays.equals(data, otherData));
129
130 byte[] extra = (this.extra != null && this.extra.length == 0) ?
131 null : this.extra;
132 check(Arrays.equals(extra, e.getExtra()));
133
134 check(name.equals(e.getName()));
135 check(method == e.getMethod());
136 check(e.getSize() == -1 || e.getSize() == data.length);
137 check((method == ZipEntry.DEFLATED) ||
138 (e.getCompressedSize() == data.length));
139
140 }
141 }
142
143 private static int uniquifier = 86;
144 private static String uniquify(String name) {
145 return name + (uniquifier++);
146 }
147
148 private static byte[] toBytes(String s) throws Exception {
149 return s.getBytes("UTF-8");
150 }
151
152 private static byte[] toExtra(byte[] bytes) throws Exception {
153 if (bytes == null) return null;
154
155 byte[] v = new byte[bytes.length + 4];
156 v[0] = (byte) 0x47;
157 v[1] = (byte) 0xff;
158 v[2] = (byte) bytes.length;
159 v[3] = (byte) (bytes.length << 8);
160 System.arraycopy(bytes, 0, v, 4, bytes.length);
161 return v;
162 }
163
164 private static Random random = new Random();
165
166 private static String makeName(int length) {
167 StringBuilder sb = new StringBuilder(length);
168 for (int i = 0; i < length; i++)
169 sb.append((char)(random.nextInt(10000)+1));
170 return sb.toString();
171 }
172
173 public static void main(String[] args) throws Exception {
174 File zipName = new File("x.zip");
175 int[] methods = {ZipEntry.STORED, ZipEntry.DEFLATED};
176 String[] names = {makeName(1), makeName(160), makeName(9000)};
177 byte[][] datas = {null, new byte[]{}, new byte[]{'d'}};
178 byte[][] extras = {null, new byte[]{}, new byte[]{'e'}};
179 String[] comments = {null, "", "c"};
180
181 List<Entry> entries = new ArrayList<Entry>();
182
183
184 entries.add(new Entry("meta-iNf/ManIfEst.Mf",
185 ZipEntry.STORED,
186 toBytes("maNiFest-VeRsIon: 1.0\n"),
187 toExtra(toBytes("Can manifests have extra??")),
188 "Can manifests have comments??"));
189
190
191 entries.add(new Entry("", ZipEntry.STORED, null, null, ""));
192
193 for (String name : names)
194 for (int method : methods)
195 for (byte[] data : datas)
196 for (byte[] extra : extras)
197 for (String comment : comments)
198 entries.add(new Entry(uniquify(name), method, data,
199 toExtra(extra), comment));
200
201
202
203
204 try (FileOutputStream fos = new FileOutputStream(zipName);
205 ZipOutputStream zos = new ZipOutputStream(fos))
206 {
207 for (Entry e : entries)
208 e.write(zos);
209 }
210
211
212
213
214 JarFile f = new JarFile(zipName);
215
216 check(f.getManifest() != null);
217
218 for (Entry e : entries)
219 e.verify(f);
220
221 f.close();
222
223
224
225
226 JarInputStream jis = new JarInputStream(
227 new FileInputStream(zipName));
228
229
230 check(jis.getManifest() != null);
231
232 for (Entry e : entries)
233 e.verify(jis);
234
235 jis.close();
236
237
238
239
240 zipName.deleteOnExit();
241
242 System.out.printf("passed = %d, failed = %d%n", passed, failed);
243 if (failed > 0) throw new Exception("Some tests failed");
244 }
245 }